package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.core.mapper.BorrowInfoMapper;
import com.atguigu.srb.core.pojo.entity.BorrowInfo;
import com.atguigu.srb.core.pojo.entity.Borrower;
import com.atguigu.srb.core.pojo.entity.Lend;
import com.atguigu.srb.core.pojo.entity.UserInfo;
import com.atguigu.srb.core.pojo.vo.*;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.result.ResponseEnum;
import com.atguigu.srb.util.JwtUtils;
import com.atguigu.srb.util.SrbAssert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 借款信息表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2024-04-15
 */
@Service
public class BorrowInfoServiceImpl extends ServiceImpl<BorrowInfoMapper, BorrowInfo> implements BorrowInfoService {
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private LendService lendService;
    @Resource
    private IntegralGradeService integralGradeService;
    @Resource
    private DictService dictService;
    @Resource
    private BorrowerService borrowerService;

    @Override
    public void saveBorrowInfo(String token, BorrowInfo borrowInfo) {
        // 1. 校验用户的基本信息
//        Long userId = JwtUtils.getUserId(token);
        UserInfo userInfo = userInfoService.checkUserBaseInfo(token);
        Long userId = userInfo.getId();
        // 2. 校验用户的借款需求
        //    2.1 校验用户是否已经有未处理完成的借款了
        //            CHECK(0, "待发布"),
        //            INVEST_RUN(1, "募资中"),
        //            PAY_RUN(2, "还款中"),
        //            PAY_OK(3, "已结清"),
        //            FINISH(4, "结标"),
        //            CANCEL(-1, "已撤标"),
        // 如果借款信息表中，用户的借款信息为审核中，则不能继续借款(因为已经申请过一次了，并且还没有处理)
        Integer count = this.count(Wrappers.lambdaQuery(BorrowInfo.class).eq(BorrowInfo::getUserId, userId)
                .eq(BorrowInfo::getStatus, 1));
        SrbAssert.assertTrue(count == 0, ResponseEnum.USER_HAS_BORROW_NOT_HANDLE);
        List<Lend> list = lendService.list(Wrappers.lambdaQuery(Lend.class).eq(Lend::getUserId, userId));
        for (Lend lend : list) {
            Integer lendStatus = lend.getStatus();
            SrbAssert.assertTrue(lendStatus == 3 || lendStatus == 4 || lendStatus == -1, ResponseEnum.USER_HAS_BORROW_NOT_HANDLE);
        }
        //    2.2 校验借款金额是否合适
        BigDecimal borrowAmount = integralGradeService.getBorrowAmountByToken(token);
        BigDecimal borrowMoney = borrowInfo.getAmount();
        SrbAssert.assertTrue(borrowAmount.compareTo(borrowMoney) == 1, ResponseEnum.USER_AMOUNT_LESS_ERROR);
        //    2.3 保存到数据库中，等待管理员审核
        borrowInfo.setUserId(userId);
        borrowInfo.setStatus(1);
        this.save(borrowInfo);
    }

    @Override
    public void getBorrowInfoListByToken(String token, Page<BorrowInfo> page) {
        Long userId = JwtUtils.getUserId(token);
        this.page(page, Wrappers.lambdaQuery(BorrowInfo.class).eq(BorrowInfo::getUserId, userId));
        HashMap<String, String> params = new HashMap<>();
        for (BorrowInfo borrowInfo : page.getRecords()) {
            // 优化查询出来的borrowInfo对象  ---> 将部分int类型转换为string类型存储到map中
            Integer status = borrowInfo.getStatus();
            switch (status) {
                case 0:
                    params.put("status", "未提交");
                    break;
                case 1:
                    params.put("status", "审核中");
                    break;
                case 2:
                    params.put("status", "审核通过");
                    break;
                case -2:
                    params.put("status", "已撤销");
                    break;
                case -1:
                    params.put("status", "审核不通过");
                    break;
            }
            // 还款方式，存储到数据字典中
            params.put("returnMethod", dictService.getNameByDictCodeAndValue("returnMethod", borrowInfo.getReturnMethod()));
            // 资金用途，存储到数据字典中
            params.put("moneyUse", dictService.getNameByDictCodeAndValue("moneyUse", borrowInfo.getMoneyUse()));
            borrowInfo.setParams(params);
        }

    }

    @Override
    public void cancelBorrowRequest(String token, Long borrowId) {
        // 撤销操作： 用户必须要登陆
        // 只能撤销自己的借款申请
        Long userId = JwtUtils.getUserId(token);
        boolean isOk = this.update(Wrappers.lambdaUpdate(BorrowInfo.class).eq(BorrowInfo::getUserId, userId)
                .eq(BorrowInfo::getId, borrowId).set(BorrowInfo::getStatus, -2));
        SrbAssert.assertTrue(isOk, ResponseEnum.USER_BORROW_REQUEST_CANCEL);
    }

    /**
     * 条件查询：
     * 姓名|手机号作为关键字模糊查询
     * 借款金额区间查询
     * 借款期限区间查询
     * 还款方式查询
     * 资金用途查询
     * 年利化率区间查询
     * 状态查询
     * 申请时间区间查询
     *
     * @param pageNum
     * @param pageSize
     */
    @Override
    public Page<BorrowInfoVO> getBorrowInfoVOList(Integer pageNum, Integer pageSize, BorrowInfoSearchVO borrowInfoSearchVO) {
        // 2表联查 -> 自定义sql -> 方法的参数为 `QueryWrapper` ，并且标识为ew。 如果是分页查询，则方法的参数为`Page`
        Page<BorrowInfoVO> borrowInfoPage = new Page<>(pageNum, pageSize);   // 分页查询 Page的泛型为查询结果的集合中实体类的泛型
        QueryWrapper<BorrowInfoVO> wrapper = new QueryWrapper<>();
        // borrowInfoId的条件查询
        if (borrowInfoSearchVO.getBorrowInfoId() != null) {
            wrapper.eq("t1.id", borrowInfoSearchVO.getBorrowInfoId());
        }
        // 查询条件的拼接
        // 姓名手机号作为关键字模糊查询
        if (StringUtils.isNotBlank(borrowInfoSearchVO.getKeyword())) {
            wrapper.and(queryWrapper -> {
                queryWrapper.like("t2.name", borrowInfoSearchVO.getKeyword()).or().like("t2.mobile", borrowInfoSearchVO.getKeyword());
            });
        }
        // 还款方式查询
        Integer returnMethod = borrowInfoSearchVO.getReturnMethod();
        if (returnMethod != null) {
            wrapper.eq("t1.return_method", returnMethod);
        }
        // 资金用途查询
        Integer moneyUse = borrowInfoSearchVO.getMoneyUse();
        if (moneyUse != null) {
            wrapper.eq("t1.money_use", moneyUse);
        }
        // 状态查询
        Integer status = borrowInfoSearchVO.getStatus();
        if (status != null) {
            wrapper.eq("t1.status", status);
        }

        // 借款期限区间查询
        Integer periodStart = borrowInfoSearchVO.getPeriodStart();
        Integer periodEnd = borrowInfoSearchVO.getPeriodEnd();
        if (periodStart != null) {
            wrapper.ge("t1.period", periodStart);
        }
        if (periodEnd != null) {
            wrapper.le("t1.period", periodEnd);
        }
        //  借款金额区间查询
        BigDecimal amountStart = borrowInfoSearchVO.getAmountStart();
        BigDecimal amountEnd = borrowInfoSearchVO.getAmountEnd();
        if (amountStart != null) {
            wrapper.ge("t1.amount", amountStart);
        }
        if (amountEnd != null) {
            wrapper.le("t1.amount", amountEnd);
        }
        // 年利化率区间查询
        BigDecimal borrowYearRateStart = borrowInfoSearchVO.getBorrowYearRateStart();
        BigDecimal borrowYearRateEnd = borrowInfoSearchVO.getBorrowYearRateEnd();
        if (borrowYearRateStart != null) {
            wrapper.ge("t1.borrow_year_rate", borrowYearRateStart);
        }
        if (borrowYearRateEnd != null) {
            wrapper.le("t1.borrow_year_rate", borrowYearRateEnd);
        }
        // 申请时间区间查询
        String createTimeStart = borrowInfoSearchVO.getCreateTimeStart();
        String createTimeEnd = borrowInfoSearchVO.getCreateTimeEnd();
        if (createTimeStart != null) {
            wrapper.ge("DATE(t1.create_time)", createTimeStart);
        }
        if (createTimeEnd != null) {
            wrapper.le("DATE(t1.create_time)", createTimeEnd);
        }
        wrapper.orderByDesc("t1.create_time");
        List<BorrowInfoVO> borrowInfoVOList = baseMapper.getBorrowInfoVOList(borrowInfoPage, wrapper);
//        System.out.println("borrowInfoVOList = " + borrowInfoVOList);
//        System.out.println("borrowInfoPage.getRecords = " + borrowInfoPage.getRecords()); // []
        borrowInfoVOList.forEach(borrowInfoVO -> {
            // 优化borrowInfoVo对象中的属性
            // 还款周期的优化
            String period = borrowInfoVO.getPeriod();
            if (period != null) {
                borrowInfoVO.setPeriod(period + "个月");
            }
            // 还款方式的优化
            String returnMethod1 = borrowInfoVO.getReturnMethod();
            if (returnMethod1 != null) {
                borrowInfoVO.setReturnMethod(dictService.getNameByDictCodeAndValue("returnMethod", Integer.parseInt(returnMethod1)));
            }
            // 资金用途的优化
            String moneyUse1 = borrowInfoVO.getMoneyUse();
            if (moneyUse1 != null) {
                borrowInfoVO.setMoneyUse(dictService.getNameByDictCodeAndValue("moneyUse", Integer.parseInt(moneyUse1)));
            }
            // 借款年利率的优化
            String borrowYearRate = borrowInfoVO.getBorrowYearRate();
            if (borrowYearRate != null) {
                borrowInfoVO.setBorrowYearRate(borrowYearRate + "%");
            }
            status2String(borrowInfoVO);
        });
        borrowInfoPage.setRecords(borrowInfoVOList);
        return borrowInfoPage;
    }

    private static void status2String(BorrowInfoVO borrowInfoVO) {
        // 借款信息状态的优化
        if (borrowInfoVO.getStatus() != null) {
            String borrowInfoVOStr = "";
            switch (Integer.parseInt(borrowInfoVO.getStatus())) {
                case 0:
                    borrowInfoVOStr = "未提交";
                    break;
                case 1:
                    borrowInfoVOStr = "审核中";
                    break;
                case 2:
                    borrowInfoVOStr = "审核通过";
                    break;
                case -1:
                    borrowInfoVOStr = "审核不通过";
                    break;
                case -2:
                    borrowInfoVOStr = "已撤销";
                    break;
            }
            borrowInfoVO.setStatus(borrowInfoVOStr);
        }
    }

    @Override
    public BorrowDetailVO getBorrowDetail(Long borrowInfoId) {
        BorrowInfoSearchVO borrowInfoSearchVO = new BorrowInfoSearchVO();
        borrowInfoSearchVO.setBorrowInfoId(borrowInfoId);
        BorrowInfoVO borrowInfoVO = this.getBorrowInfoVOList(1, 1, borrowInfoSearchVO).getRecords().get(0);
        BorrowDetailVO borrowDetailVO = new BorrowDetailVO();
        borrowDetailVO.setBorrowInfoVO(borrowInfoVO);
        Long userId = this.getById(borrowInfoId).getUserId();
        Long borrowerId = borrowerService.getOne(Wrappers.lambdaQuery(Borrower.class).eq(Borrower::getUserId, userId)).getId();
        BorrowerApprovalVO borrowerApprovalVO = borrowerService.approvalInfo(borrowerId);
        borrowDetailVO.setBorrowerApprovalVO(borrowerApprovalVO);
        return borrowDetailVO;
    }

    @Override
    public Integer status(String token) {
        Long userId = JwtUtils.getUserId(token);
        List<BorrowInfo> list = this.list(Wrappers.lambdaQuery(BorrowInfo.class).eq(BorrowInfo::getUserId, userId)
                .ne(BorrowInfo::getStatus, -2).orderByDesc(BorrowInfo::getCreateTime).last("limit 1"));
        if (list.isEmpty()) {
            return 0;
        }
        BorrowInfo borrowInfo = list.get(0);
        return borrowInfo.getStatus();
    }

    @Override
    public void borrowInfoApproval(BorrowInfoApprovalVO borrowInfoApprovalVO) {
        // 1. 跟新借款信息的状态 -> 已通过 / 不通过
        Integer status = borrowInfoApprovalVO.getStatus();
        SrbAssert.assertTrue(status==2,ResponseEnum.BORROWINFO_APPROVAL_NOT_OK);
        BorrowInfo borrowInfo = new BorrowInfo();
        borrowInfo.setId(borrowInfoApprovalVO.getBorrowInfoId());
        borrowInfo.setStatus(0);
        this.updateById(borrowInfo);

        // 2. 如果通过，则创建标的
        if (status == -1) {
            return;
        }
        Lend lend = new Lend();
        BeanUtils.copyProperties(borrowInfoApprovalVO, lend);
        BorrowInfo borrowInfo1 = this.getById(borrowInfo.getId());
        lend.setAmount(borrowInfo1.getAmount());
//        lend.setCheckAdminId();
//        lend.setCheckTime(new Date());   // 标的的审核时间 --> 发布标的时指定
        //将借款信息年化转为月化:  年化/12=月化    前端提交的年化*100
        BigDecimal monthRate = borrowInfoApprovalVO.getLendYearRate().divide(new BigDecimal(1200), 6, BigDecimal.ROUND_DOWN);
        lend.setExpectAmount(borrowInfo1.getAmount()
                .multiply(monthRate)
                .multiply(new BigDecimal(borrowInfo1.getPeriod())));//期数*月化率*借款金额    预期收益
        lend.setInvestAmount(new BigDecimal(0));  // 已投金额
        lend.setInvestNum(0);   //投资人数
        lend.setLendEndDate(new DateTime(lend.getLendStartDate()).plusMonths(borrowInfo1.getPeriod()).toDate());  // 标的结束日期： 开始日期 + 期限
        lend.setLendNo(IdWorker.getIdStr());  //标的编号 -> 根据雪花算法来生成
        lend.setLowestAmount(new BigDecimal(50));
//        lend.setPaymentAdminId();
//        lend.setPaymentTime();
        lend.setPeriod(borrowInfo1.getPeriod());
//        lend.setPublishDate(borrowInfo1.getCreateTime());  // 此时标的还没有发布呢
        lend.setRealAmount(new BigDecimal(0));
        lend.setReturnMethod(borrowInfo1.getReturnMethod());
        lend.setUserId(borrowInfo1.getUserId());
        lendService.save(lend);
    }


}
